package com.homelock.dubbo.service;

import com.alibaba.dubbo.config.annotation.Service;
import com.homelock.common.util.CGlibMapper;
import com.homelock.common.util.DateUtils;
import com.homelock.common.vo.PageResp;
import com.homelock.common.vo.Resp;
import com.homelock.constants.Constants;
import com.homelock.constants.RedisKeyEnmu;
import com.homelock.domain.CommunityAdvDto;
import com.homelock.domain.query.ComHouseholdQuery;
import com.homelock.domain.query.ComOpenRecordQuery;
import com.homelock.entity.*;
import com.homelock.mapper.ComOpenDoorRecordMapper;
import com.homelock.mapper.HlCommunityAdvMapper;
import com.homelock.mapper.HlCommunityHouseholdMapper;
import com.homelock.service.HlCommunityHouseholdService;
import com.homelock.service.HlDevInfoService;
import com.homelock.service.LockUserService;
import com.homelock.service.SmsSendApiService;
import com.homelock.service.check.LockUserCheckUtil;
import com.homelock.vo.ComAlarmRecordVo;
import com.homelock.vo.ComSmsSendResp;
import com.homelock.vo.CommunityInfoVo;
import com.pi.base.enumerate.record.RecordState;
import com.pi.base.exception.ServiceException;
import com.pi.base.util.cache.RedisUtil;
import com.pi.base.util.time.DateTools;
import com.pi.community.dao.entity.BaseCommunityEntity;
import com.pi.community.dao.mapper.BaseCommunityMapper;
import com.pi.community.service.CommunityService;
import org.apache.http.util.Asserts;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.*;
import java.util.stream.Collectors;


/**
 * 物业相关service
 */
@Service(version = "${dubbo.version}")
@org.springframework.stereotype.Service
public class CommunityManagerServiceImpl implements CommunityManagerService{
    private static final Logger logger = LoggerFactory.getLogger(CommunityManagerServiceImpl.class);

    private HlDevInfoService hlDevInfoService;
    private LockUserService lockUserService;
    private ComOpenDoorRecordMapper comOpenDoorRecordMapper;
    private CommunityService communityService;
    private HlCommunityAdvMapper hlCommunityAdvMapper;
    private HlCommunityHouseholdService hlCommunityHouseholdService;
    private SmsSendApiService smsSendApiService;

    @Autowired
    public CommunityManagerServiceImpl(HlDevInfoService hlDevInfoService, LockUserService lockUserService,
                                       CommunityService communityService, ComOpenDoorRecordMapper comOpenDoorRecordMapper,
                                       HlCommunityAdvMapper hlCommunityAdvMapper,
                                       HlCommunityHouseholdService hlCommunityHouseholdService,
                                       SmsSendApiService smsSendApiService) {
        Assert.notNull(communityService, "名称索引基础服务为空");
        Assert.notNull(lockUserService, "名称索引基础服务为空");
        Assert.notNull(hlDevInfoService, "设备基础服务为空");
        Assert.notNull(hlCommunityHouseholdService, "社区住户基础服务为空");

        this.communityService = communityService;
        this.hlDevInfoService = hlDevInfoService;
        this.comOpenDoorRecordMapper = comOpenDoorRecordMapper;
        this.lockUserService = lockUserService;
        this.hlCommunityAdvMapper = hlCommunityAdvMapper;
        this.hlCommunityHouseholdService = hlCommunityHouseholdService;
        this.smsSendApiService = smsSendApiService;
    }


    /**
     * 查询社区关联用户的报警记录
     * @param openRecordQuery
     * @return
     */
    public PageResp queryPageAlarmListByCommunity(ComOpenRecordQuery openRecordQuery){
        Asserts.notNull(openRecordQuery,"openRecordQuery");
        Asserts.notNull(openRecordQuery.getCommunityId(),"communityId");
        Long communityId = openRecordQuery.getCommunityId();
        Asserts.check(communityId != 0,"社区id为0");
        List<HlDevInfo> devInfos = hlDevInfoService.queryListByCommunityId(communityId);
        if(CollectionUtils.isEmpty(devInfos)){
            return PageResp.emptyPage();
        }
        List<Long> devIds = devInfos.stream().map(HlDevInfo::getId).collect(Collectors.toList());
        Map<String,Object> queryMap = new HashMap(16);
        //  社区关联的全部设备
        queryMap.put("devIds",devIds);
        queryMap.put("communityId",communityId);
        // 报警类型
        if(null != openRecordQuery.getOpmode()){
            queryMap.put("opmode",openRecordQuery.getOpmode());
        }
        // 用户名称模糊查询的相关设备
        if(!StringUtils.isEmpty(openRecordQuery.getUserName())){
            queryMap.put("userName","%"+openRecordQuery.getUserName().trim()+"%");
        }
        if(openRecordQuery.getLimit() != null && openRecordQuery.getOffset() !=null){
            // 分页参数校验
            if(openRecordQuery.getOffset()<0){
                openRecordQuery.setOffset(0);
            }
            if(openRecordQuery.getLimit() <0 || openRecordQuery.getLimit() > 100){
                openRecordQuery.setLimit(100);
            }
            queryMap.put("limit",openRecordQuery.getLimit());
            queryMap.put("offset",openRecordQuery.getOffset());
        }
        List<ComAlarmRecordVo> list = comOpenDoorRecordMapper.queryAlarmPageListByCommunityId(queryMap);
        Integer count = comOpenDoorRecordMapper.countAlarmPageListByCommunityId(queryMap);
        if(CollectionUtils.isEmpty(list)){
            return new PageResp(new ArrayList(),count);
        }
        // 查询设备相关的信息
        Map<Long,HlDevInfo> devInfoMap = devInfos.stream().collect(Collectors.toMap(HlDevInfo::getId,devInfo -> devInfo));
        List<ComAlarmRecordVo> result = new ArrayList<>(list.size());
        for(ComAlarmRecordVo record : list){
            // 设备相关
            Long devId = record.getDevId();
            HlDevInfo devInfo = devInfoMap.get(devId);
            record.setDevImei(devInfo.getDevImei());
            record.setDevName(devInfo.getDevName() == null ? "" : devInfo.getDevName());
            record.setOpTime(DateTools.getFullDate(record.getCreateDate()));
            // 查询当前报警用户对应的信息
            if(record.getSourceUserId() != null && record.getSourceUserId() != 0L){
                HlDevUser hlDevUser = lockUserService.queryByIdAndDevId(record.getSourceUserId(),devId);
                record.setSourceUserName(hlDevUser == null ? "" : hlDevUser.getDevUserName());
            }
            result.add(record);
        }
        return new PageResp(result,count);
    }


    /**
     * 更新物业的联系方式
     * @param communityId
     * @param contact
     * @return
     */
    public Resp updateCommunityContact(Long communityId, String contact){
        Asserts.notNull(communityId,"communityId");
        LockUserCheckUtil.validateMobile(contact);
        contact = contact.trim();
        // 验证手机号是否更改，更改之后是否重复
        BaseCommunityEntity entity = communityService.findOne(communityId);
        if (null == entity ) {
            return Resp.faild("小区不存在，无法更新",null);
        }
        // 联系方式不同 查询是否重复 不重复则更新
        if(StringUtils.isEmpty(entity.getContact()) || !contact.equals(entity.getContact())){
            BaseCommunityEntity contactEntity = communityService.findByContact(contact);
            if(contactEntity != null){
                return Resp.faild("联系方式被占用，无法更新",null);
            }
            entity.setContact(contact);
            entity.setUpdateDate(new Date());
            boolean flag = communityService.updateById(entity) > 0;
            if(flag){
                return Resp.ok();
            }
        }
        return Resp.ok();
    }

    /**
     * 查询社区的基础信息
     * @param communityId
     * @return
     */
    public CommunityInfoVo queryById(Long communityId){
        BaseCommunityEntity entity = communityService.findOne(communityId);
        if(entity != null){
            CommunityInfoVo communityInfoVo = new CommunityInfoVo();
            CGlibMapper.mapperObject(entity,communityInfoVo);
            return communityInfoVo;
        }
        return null;
    }

    /**
     * 查询社区的基础信息
     * @param id
     * @return
     */
    public CommunityAdvDto queryAdvById(Long id,Long communityId){
        Asserts.notNull(id,"advId");
        Asserts.notNull(communityId,"communityId");
        //HlCommunityAdv communityAdv = hlCommunityAdvMapper.selectByPrimaryKey(id);
        HlCommunityAdvExample example = new HlCommunityAdvExample();
        example.createCriteria().andStateEqualTo(RecordState.STATE_NORMAL.getState()).andIdEqualTo(id).andCommunityIdEqualTo(communityId);
       List<HlCommunityAdv> list = hlCommunityAdvMapper.selectByExample(example);
       if(CollectionUtils.isEmpty(list)){
           return null;
       }
        return CGlibMapper.mapper(list.get(0),CommunityAdvDto.class);
    }

    /**
     * 新增广告接口
     * @param communityAdvDto
     * @return
     */
    public Resp addCommunityAdv(CommunityAdvDto communityAdvDto){
        Asserts.notNull(communityAdvDto,"communityAdvDto");
        Asserts.notNull(communityAdvDto.getCommunityId(),"communityId");
        Asserts.check((!StringUtils.isEmpty(communityAdvDto.getPicUrl()) || !StringUtils.isEmpty(communityAdvDto.getThumbnailUrl())),
    "至少传一张广告图片");
        // 当前物业所有广告数
        int size = countAdvByCommunityId(communityAdvDto.getCommunityId());
        if(size >= Constants.MAX_COMMUNITY_ADV_SIZE){
            return Resp.faild("广告数量已达到"+Constants.MAX_COMMUNITY_ADV_SIZE+"张,新增失败",null);
        }
        // 转换成实体类
        HlCommunityAdv hlCommunityAdv = communityAdvDto.convertToEntity();
       /* if(hlCommunityAdv.getAdvSort() == null || hlCommunityAdv.getAdvSort() == 0){
            hlCommunityAdv.setAdvSort((byte)(size+1));
        }*/
        // 保存
      //  hlCommunityAdv.set
        hlCommunityAdvMapper.insert(hlCommunityAdv);
        return Resp.ok();
    }

    /**
     * 修改广告接口
     * @param communityAdvDto
     * @return
     */
    public Resp updateCommunityAdv(CommunityAdvDto communityAdvDto){
        Asserts.notNull(communityAdvDto,"communityAdvDto");
        Asserts.notNull(communityAdvDto.getId(),"广告id");
        Asserts.notNull(communityAdvDto.getCommunityId(),"communityId");
        Asserts.check((!StringUtils.isEmpty(communityAdvDto.getPicUrl()) || !StringUtils.isEmpty(communityAdvDto.getThumbnailUrl())),
                "至少传一张广告图片");

        HlCommunityAdv pre = hlCommunityAdvMapper.selectByPrimaryKey(communityAdvDto.getId());
        if(pre == null || pre.getState() == RecordState.STATE_DELETE.getState()){
            return Resp.faild("该广告信息不存在",null);
        }
        // 转换成实体类
        HlCommunityAdv hlCommunityAdv = communityAdvDto.convertToEntity();
        /*if(hlCommunityAdv.getAdvSort() == null || hlCommunityAdv.getAdvSort() == 0){
            hlCommunityAdv.setAdvSort(pre.getAdvSort());
        }*/
        hlCommunityAdv.setVersion(pre.getVersion()+1);
        hlCommunityAdv.setCreateDate(pre.getCreateDate());
        hlCommunityAdv.setState(pre.getState());
        hlCommunityAdv.setCommunityId(pre.getCommunityId());
        // 更新
        hlCommunityAdvMapper.updateByPrimaryKey(hlCommunityAdv) ;
        return Resp.ok();
    }

    /**
     * 删除广告信息
     * @param id
     * @return
     */
    public Resp deleteCommunityAdv(Long id){
        HlCommunityAdv pre = hlCommunityAdvMapper.selectByPrimaryKey(id);
        pre.setState(RecordState.STATE_DELETE.getState());
        hlCommunityAdvMapper.updateByPrimaryKey(pre) ;
        return Resp.ok();
    }

    @Override
    public PageResp queryPageAdv(ComOpenRecordQuery openRecordQuery) {
        Asserts.notNull(openRecordQuery,"query");
        Asserts.notNull(openRecordQuery.getCommunityId(),"communityId");
        Long communityId = openRecordQuery.getCommunityId();
        Asserts.check(communityId != 0,"社区id为0");
        HlCommunityAdvExample example = new HlCommunityAdvExample();
        HlCommunityAdvExample.Criteria criteria = example.createCriteria();
        criteria.andCommunityIdEqualTo(communityId).andStateEqualTo(RecordState.STATE_NORMAL.getState());
        if(null != openRecordQuery.getLimit() && null != openRecordQuery.getOffset()){
            example.setOrderByClause(" id  LIMIT "+openRecordQuery.getOffset()+" , "+openRecordQuery.getLimit());
        }
        List<HlCommunityAdv> list = hlCommunityAdvMapper.selectByExample(example);
        int count = hlCommunityAdvMapper.countByExample(example);
        if(CollectionUtils.isEmpty(list)){
            return new PageResp(new ArrayList(0),count);
        }
        List result = new ArrayList();
        for(HlCommunityAdv dto:list){
            CommunityAdvDto temp = new CommunityAdvDto();
            temp.setId(dto.getId());
            temp.setCommunityId(dto.getCommunityId());
            temp.setThumbnailUrl(dto.getThumbnailUrl());
            temp.setPicUrl(dto.getPicUrl());
            temp.setCreateDate(DateUtils.date2String(dto.getCreateDate(),DateUtils.ISO_DATETIME_FORMAT));
            result.add(temp);
        }
        return new PageResp(result,count);
    }

    @Override
    public Resp insertCommunityHousehold(Long communityId, String householdName, String householdContact,String adress) {
        // 不check物业用户的联系方式是否重复幸，存在一人多户的可能性
        Asserts.notNull(communityId,"物业ID");
        Asserts.notNull(householdContact,"物业住户电话");
        Asserts.notNull(householdName,"物业住户姓名");
        LockUserCheckUtil.validateMobile(householdContact);
        return hlCommunityHouseholdService.insert(communityId,householdName,householdContact,adress);
    }

    @Override
    public Resp updateCommunityHousehold(Long id, String householdName, String householdContact,String address) {
        Asserts.notNull(id,"ID");
        Asserts.notNull(householdContact,"物业住户电话");
        Asserts.notNull(householdName,"物业住户姓名");
        return hlCommunityHouseholdService.update(id,householdName,householdContact,address);
    }

    @Override
    public Resp delCommunityHousehold(Long id) {
        boolean flag = hlCommunityHouseholdService.delete(id);
        if(flag){
            return Resp.ok();
        }
        return Resp.faild("删除失败",null);
    }

    @Override
    public Resp delCommunityHouseholds(List<Long> ids) {
        boolean flag = hlCommunityHouseholdService.deleteByIds(ids);
        if(flag){
            return Resp.ok();
        }
        return Resp.faild("删除失败",null);
    }

    @Override
    public PageResp queryPageHousehold(ComHouseholdQuery comHouseholdQuery) {
        return hlCommunityHouseholdService.queryPageHousehold(comHouseholdQuery);
    }

    @Override
    public Resp sendBatchCommunityNoice(Long communityId, List<Long> housholdIds, String smsContent) {
        if(communityId == null){
            return Resp.faild("communityId不能为空",null);
        }
        if(CollectionUtils.isEmpty( housholdIds)){
            return Resp.faild("没有需要发送短信的id",null);
        }
        if(StringUtils.isEmpty(smsContent)){
            return Resp.faild("物业通知不能为空",null);
        }
        // 查询当前社区是否可以发对应的数量短信
        int sendNum = hlCommunityHouseholdService.querySmsSendNumByCommunityId(communityId);
        if(sendNum < housholdIds.size()){
            return Resp.faild("您当前可发送短信的数量"+sendNum+"条，无法给当前选中的用户发送物业通知，请联系微信号："+"wx12345",
                    null);
        }
        // 发送物业通知
        List<String> phoneList = hlCommunityHouseholdService.queryPhoneByCommunityIdAndIds(communityId,housholdIds);
        if(phoneList == null){
            return Resp.faild("查询不到需要发送短信的住户电话",null);
        }
        // 完成之后自动删除key
        logger.info("sendComSms-currentTime:"+DateTools.getCurDate(DateTools.FORMAT_SIMPLEDATETIME));
        Long startTime = System.currentTimeMillis();
        String lockKey = RedisKeyEnmu.COM_SMS_LOCK_KEY.getKey()+communityId;
        boolean flag = RedisLockUtil.trylock(lockKey,startTime.toString(),60);
        if(!flag){
            // 获取锁失败
            long munite = (startTime - Long.valueOf(RedisLockUtil.getLong(lockKey))) / 1000;
            return Resp.faild("下次发物业通知还需"+munite+"秒",null);
        }
        smsSendApiService.sendCommunityNotice(communityId,phoneList,smsContent);
        ComSmsSendResp resp = new ComSmsSendResp();
        resp.setTotal(phoneList.size());
        RedisLockUtil.releaseDistributedLock(lockKey,startTime.toString());
        return Resp.ok(resp);
    }

    private int countAdvByCommunityId(Long communityId){
        HlCommunityAdvExample hlCommunityAdvExample = new HlCommunityAdvExample();
        hlCommunityAdvExample.createCriteria().andCommunityIdEqualTo(communityId).andStateEqualTo(RecordState.STATE_NORMAL.getState());
        return hlCommunityAdvMapper.countByExample(hlCommunityAdvExample);
    }

}
